﻿using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.EntityFrameworkCore.EFPlus;
using Abp.Extensions;
using Abp.ObjectMapping;
using Abp.Runtime.Session;
using Castle.Core.Logging;
using Mt.Site.Core.WorkFlows.Diy;
using Mt.Site.Core.WorkFlows.Enum;
using Mt.Site.Core.WorkFlows.Process.Entities;
using Mt.Site.Core.WorkFlows.Process.Models;
using Mt.Site.Core.WorkFlows.Process.Stores;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Core.WorkFlows.Process.Impl
{
    public class WorkFlowRollBackData
    {
        public List<Guid> IdListToRemve { get; set; }

        public List<Guid> IdListToChangeToWaiting { get; set; }

        public List<Guid> IdListToFinished { get; set; }

        public List<Guid> IdListToDo { get; set; }

        public List<WorkFlowProcessDto> Records { get; set; }

        public List<WorkFlowRelationshipDto> RelationshipsWithCanceled { get; set; }
        public List<WorkFlowRelationshipDto> Relationships { get; set; }
        public Guid BackToNodeId { get; set; }

        public int BackToStepCode { get; set; }

        public WorkFlowProcessDto SelectedTask { get; set; }
    }

    public class WorkFlowRollBackService : IWorkFlowRollBackService, ITransientDependency
    {
        private readonly IRepository<WorkFlowPaper, Guid> _workFlowPaperRepository;
        public IRepository<WorkFlowProcess, Guid> WorkFlowProcessRepository { get; private set; }
        public IRepository<WorkFlowLogs, long> WorkFlowLogsRepository { get; private set; }

        private readonly IRepository<WorkFlowRelationship, long> _workFlowRelationshipRepository;
        private readonly IRepository<WorkFlowProcessMsg, long> _workFlowProcessMsgRepository;

        private readonly IWorkFlowProcessStore _workFlowProcessService; 

        public IObjectMapper ObjectMapper { get; set; }
        public ILogger Loger { get; set; }
        public IAbpSession AbpSession { get; set; }

        public WorkFlowRollBackService(
            IRepository<WorkFlowPaper, Guid> workFlowPaperRepository,
            IRepository<WorkFlowProcess, Guid> workFlowProcesRepository,
            IRepository<WorkFlowLogs, long> workFlowLogsRepository,
            IRepository<WorkFlowRelationship, long> workFlowRelationshipRepository,
            IRepository<WorkFlowProcessMsg, long> workFlowProcessMsgRepository,
            IWorkFlowProcessStore workFlowProcessService)
        {
            _workFlowPaperRepository = workFlowPaperRepository;
            WorkFlowProcessRepository = workFlowProcesRepository;
            WorkFlowLogsRepository = workFlowLogsRepository;
            _workFlowRelationshipRepository = workFlowRelationshipRepository;
            _workFlowProcessMsgRepository = workFlowProcessMsgRepository;
            _workFlowProcessService = workFlowProcessService;

            AbpSession = NullAbpSession.Instance;
            ObjectMapper = NullObjectMapper.Instance;
            Loger = NullLogger.Instance;
        }


        /// <inheritdoc/>
        public async Task<bool> CheckWithdrawBtnState(IWorkFlowManager manager)
        {
            var paper = manager.CurrentPaper?.Paper;
            if (paper != null && paper.PaperState == PaperState.Running)
            {
                var records = await manager.GetAllProcessDataWithArchiveAsync();
                //当前的操作人的id
                long userid = manager.UserId;

                WorkFlowProcessDto taskModel = await FindTaskDataForWithdraw(records, userid, manager);

                if (taskModel != null)
                {
                    var relationshipsWithCanceled = await manager.GetWorkFlowRelationshipsWithCanceledAsync();
                    var taskId = taskModel.Id;
                    var workFlowRollBackDiyService = manager.WorkFlowPluginFunction.WorkFlowRollBackDiyService;
                    WorkFlowRollBackData rollBackData = CheckRollBackData(taskId, records, relationshipsWithCanceled, workFlowRollBackDiyService);
                    if(rollBackData != null)
                    {
                        return await CheckStateForWithdrawAsync(rollBackData, workFlowRollBackDiyService, taskModel , false);
                    }
                }
            }
            return false;
        }


        /// <inheritdoc/>
        public async Task<Guid> WithdrawAsync(IWorkFlowManager manager, bool cleanMsg)
        {
            var paper = manager.CurrentPaper?.Paper;
            if (paper != null && paper.PaperState == PaperState.Running)
            {
                var records = await manager.GetAllProcessDataWithArchiveAsync();
                //当前的操作人的id
                long userid = manager.UserId;

                WorkFlowProcessDto taskModel = await FindTaskDataForWithdraw(records, userid, manager);

                if (taskModel != null)
                {
                    var relationshipsWithCanceled = await manager.GetWorkFlowRelationshipsWithCanceledAsync();
                    var taskId = taskModel.Id;
                    var workFlowRollBackDiyService = manager.WorkFlowPluginFunction.WorkFlowRollBackDiyService;
                    WorkFlowRollBackData rollBackData = CheckRollBackData(taskId, records, relationshipsWithCanceled, workFlowRollBackDiyService);
                    if (rollBackData != null)
                    {
                        var canOp = await CheckStateForWithdrawAsync(rollBackData, workFlowRollBackDiyService, taskModel , false);

                        if (canOp)
                        {
                            await CheckRollBackDataBeforeWithdrawAsync(workFlowRollBackDiyService, rollBackData);

                            await ChangeDbDataForGoBackActionAsync(taskId, rollBackData, paper, workFlowRollBackDiyService, cleanMsg);
                            return taskId;
                        }
                    }

                }
            }

            return Guid.Empty;
        }

        #region private

        //检查撤回操作是否可以执行
        private static async Task<bool> CheckStateForWithdrawAsync(
            WorkFlowRollBackData rollBackData, 
            IWorkFlowRollBackDiyService workFlowRollBackDiyService,
            WorkFlowProcessDto taskModel,
            bool forced)
        {
            //多人并行中已由其他人提交到下一环节或送回支线发起人
            if (rollBackData.IdListToFinished.Count > 0)
            {
                return false;
            }

            // 后续的操作人已经看过稿件
            var list = rollBackData.Records.Where(
                c => rollBackData.IdListToRemve.Contains(c.Id) || rollBackData.IdListToChangeToWaiting.Contains(c.Id));
            foreach (var item in list)
            {
                if (forced)
                {
                    if (item.State == ActionState.Related)
                    {
                        return false;
                    }
                }
                else
                {
                    if (item.HasMarked)
                    {
                        return false;
                    }
                }
            }


            //  多对1的关系， 如一个领导的待办任务同时审核多个并行的办理人提交
            foreach (var item in rollBackData.Relationships)
            {
                //TaskId 对应的任务数据 是 被关联者，ResponsibilityId 对应的 任务数据 是责任链源头
                //所以要优先使用WorkflowProcess的ResponsibilityId，否则稿件可能无法撤回
                if (rollBackData.IdListToDo.Contains(item.ResponsibilityId))
                {
                    var task = rollBackData.Records.FirstOrDefault(c => c.Id == item.TaskId);
                    if (forced)
                    {
                        return task == null || task.State != ActionState.Related;
                    }
                    else
                    {
                        return task == null || task.HasMarked == false || item.HasMarked == false;
                    }
                }
            }

            if (workFlowRollBackDiyService != null)
            {
                return await workFlowRollBackDiyService.CheckStateForWithdrawAsync(rollBackData, taskModel, forced);
            }

            return true;
        }

        //查找申请撤回的人员最后一项操作任务
        private static async Task<WorkFlowProcessDto> FindTaskDataForWithdraw(List<WorkFlowProcessDto> records, long userid, IWorkFlowManager manager)
        {
            WorkFlowProcessDto tempItem = null;
            var actionState = await manager.CheckActionStateAsync();

            for (int i = 0, length = records.Count; i < length; i++)
            {
                var item = records[i];
                if (item.UserId == userid && item.State == ActionState.Related)
                {
                    if(actionState == ActionState.Todo && item.OperationType == OperationType.PassRound)
                    {
                        //待办状态 不撤回 传阅
                        continue;
                    }

                    if(tempItem == null || tempItem.FinishedTime < item.FinishedTime)
                    {
                        tempItem = item;
                    } 
                    else if(tempItem.FinishedTime == item.FinishedTime)
                    {
                        if (item.Severity > tempItem.Severity)
                        {
                            tempItem = item;
                        }
                        else if(item.Severity == tempItem.Severity && item.OperationType == OperationType.Processing)
                        {
                            tempItem = item;
                        }
                    }
                }
            }
            //当前用户的最后一条在办信息
            WorkFlowProcessDto taskModel = tempItem == null ? null : tempItem.CloneANewOne();

            return taskModel;
        }


        private async Task CheckRollBackDataBeforeWithdrawAsync(IWorkFlowRollBackDiyService workFlowRollBackDiyService, WorkFlowRollBackData rollBackData)
        {
            //撤回时可以移除的都是未查看的任务(查找可能被移除的(多对1关系里的那个1))
            var removeList = rollBackData.Records
                .Where(c => rollBackData.IdListToRemve.Contains(c.Id) && c.ResponsibilityId != null && c.TrunkId == null)
                .ToList();

            var relationships = rollBackData.Relationships;

            var remainItems = new List<Guid>();
            foreach (var item in removeList)//应该只有一个
            {
                //查找有无其他人员也关联着这条待移除的任务
                var idList = relationships.Where(c => c.TaskId == item.Id).Select(c => c.ResponsibilityId);
                var taskList = rollBackData.Records.Where(c => idList.Contains(c.Id) && c.State == ActionState.Related && c.FinishedByTheWay == null).ToList();

                if (taskList.Count > 0)
                {
                    remainItems.Add(item.Id);

                    var receiver = taskList.OrderBy(c => c.FinishedTime).First();
                    var oldRelationShip = WorkFlowStaticFuncCollection.MoveLeaderTask(item, receiver, relationships);

                    await _workFlowProcessService.UpdateAsync(item);

                    await _workFlowRelationshipRepository.DeleteAsync(oldRelationShip.Id);
                }
            }
            if (remainItems.Count > 0)
            {
                rollBackData.IdListToRemve = rollBackData.IdListToRemve.Where(c => !remainItems.Contains(c)).ToList();
            }

            if (workFlowRollBackDiyService != null)
            {
                await workFlowRollBackDiyService.CheckRollBackDataBeforeWithdrawAsync(rollBackData.SelectedTask, rollBackData, this);
            }
        }

        #endregion

        /// <inheritdoc/>
        public async Task RollBackAsync(Guid taskId, Guid paperId, IWorkFlowRollBackDiyService workFlowRollBackDiyService)
        {
            var paper = await _workFlowPaperRepository.FirstOrDefaultAsync(c => c.Id == paperId);
            if (paper != null && paper.PaperState == PaperState.Running)
            {
                //不在这里自己调取了，统一调取规则，避免重构代码引起纰漏
                var records = await _workFlowProcessService.GetAllProcessDataWithArchiveAsync(paperId);
                var relationshipsWithCanceled = await _workFlowProcessService.GetWorkFlowRelationshipsWithCanceledAAsync(paperId);
                WorkFlowRollBackData rollBackData = CheckRollBackData(taskId, records, relationshipsWithCanceled, workFlowRollBackDiyService);

                if (rollBackData != null)
                {
                    var canOp = await CheckStateForWithdrawAsync(rollBackData, workFlowRollBackDiyService, rollBackData.SelectedTask, true);
                    if (canOp)
                    {
                        await CheckRollBackDataBeforeWithdrawAsync(workFlowRollBackDiyService, rollBackData);
                        await ChangeDbDataForGoBackActionAsync(taskId, rollBackData, paper, workFlowRollBackDiyService, true);
                    }
                    else
                    {
                        //Act
                        await ChangeDbDataForGoBackActionAsync(taskId, rollBackData, paper, workFlowRollBackDiyService, true);
                    }
                }
            }
        }

        #region private

        private WorkFlowRollBackData CheckRollBackData(Guid taskId, List<WorkFlowProcessDto> records, List<WorkFlowRelationshipDto> RelationshipsWithCanceled,
            IWorkFlowRollBackDiyService workFlowRollBackDiyService)
        {
            WorkFlowRollBackData rollBackData = null;

            var taskData = records.FirstOrDefault(c => c.Id == taskId);
            if (taskData != null && taskData.State == ActionState.Related)
            {
                rollBackData = new WorkFlowRollBackData
                {
                    IdListToRemve = new List<Guid>(),                //需删除的
                    IdListToChangeToWaiting = new List<Guid>(),      //需改为等待的
                    IdListToFinished = new List<Guid>(),             //日志内容改为已办理（多人并行）
                    IdListToDo = new List<Guid>(),
                    Records = records,
                    RelationshipsWithCanceled = RelationshipsWithCanceled,
                    Relationships = RelationshipsWithCanceled.Where(c => c.IsCanceled == false).ToList(),
                    SelectedTask = taskData
                };

                /*
                   1、 自己的下级(移除)  及 自己（改为todo）
                   2、 沿主干依次遍历所有父节点直至回到主干（处理多人顺序，多人并行的问题）。
                   3、 用preStepId串起树结构，而用trunkId结合preStepId来查找及校验
                */

                rollBackData.IdListToRemve.AddRange(GetAllDescendant(taskData.Id, records, false));
                rollBackData.IdListToDo.Add(taskData.Id);

                //查询
                CheckRollBackDataInternalAysnc(taskData, rollBackData, workFlowRollBackDiyService);


                //待办任务办结时一起结束掉的传阅，也要一起恢复（传阅是多人并行，恢复时直接恢复为待办）
                var passRoundList = rollBackData.Records
                    .Where(c => (c.State == ActionState.Related || c.State == ActionState.Archive) && c.FinishedByTheWay != null)
                    .OrderBy(c => c.StartTime);
                foreach (var item in passRoundList)
                {
                    if (rollBackData.IdListToDo.Contains(item.FinishedByTheWay.Value)
                       || rollBackData.IdListToRemve.Contains(item.FinishedByTheWay.Value)
                       || rollBackData.IdListToChangeToWaiting.Contains(item.FinishedByTheWay.Value))
                    {
                        if (!rollBackData.IdListToRemve.Contains(item.Id)
                            && !rollBackData.IdListToDo.Contains(item.Id)
                            && !rollBackData.IdListToChangeToWaiting.Contains(item.Id)) 
                        {
                            if (item.WaitingList.IsNullOrEmpty())
                            {
                                rollBackData.IdListToDo.Add(item.Id);
                            }
                            else
                            {
                                var waiting = item.WaitingList.GetArryFromStrBySplit<Guid>(WorkFlowConst.SplitChars);
                                if (rollBackData.IdListToDo.FirstOrDefault(c => waiting.Contains(c)) != Guid.Empty
                                    || rollBackData.IdListToChangeToWaiting.FirstOrDefault(c => waiting.Contains(c)) != Guid.Empty)
                                {
                                    rollBackData.IdListToChangeToWaiting.Add(item.Id);
                                }
                                else
                                {
                                    rollBackData.IdListToDo.Add(item.Id);
                                }
                            }
                        }
                    }
                }
            }

            return rollBackData;
        }

        private void CheckRollBackDataInternalAysnc(WorkFlowProcessDto task, WorkFlowRollBackData rollBackData,
            IWorkFlowRollBackDiyService workFlowRollBackDiyService)
        {
            // 多人顺序(兄弟移除后代，兄弟自己改为等待）
            // 多人并行（在其他分支找寻多人并行的最后一个操作者，若存在，则该兄弟移除后代，改为已完成）
            CheckBrothers(task, rollBackData, workFlowRollBackDiyService);

            // 沿主干依次遍历所有父节点直至回到主干
            bool isBranchLine = task.TrunkId != null;
            if (isBranchLine)
            {
                WorkFlowProcessDto parentTask = rollBackData.Records.First(c => c.Id == task.TrunkId);
                CheckRollBackDataInternalAysnc(parentTask, rollBackData, workFlowRollBackDiyService);
            }
        }

        //遍历所有同级分支找出要调整的任务数据
        private void CheckBrothers(WorkFlowProcessDto task, WorkFlowRollBackData rollBackData,
            IWorkFlowRollBackDiyService workFlowRollBackDiyService)
        {
            if (task.TrunkId != null)
            {
                //目前为止分支流转中还没有跨步骤的设定，所有如果撤回发生在某个分支，可以用来定位StepCode
                rollBackData.BackToStepCode = task.StepCode;
                rollBackData.BackToNodeId = task.NodeId;

                var parallelList = rollBackData.Records
                    .Where(c => c.StepCode == task.StepCode && c.TrunkId == task.TrunkId && c.Code != task.Code).ToList();
                if (parallelList.Count > 0)
                {
                    //避免取到后期添加的任务（PreStepId的值不对，支线送回的那条任务或其他自定义操作新增的任务）
                    var creationTime = parallelList.Select(c => c.CreationTime).Min();
                    parallelList = parallelList.Where(c => c.CreationTime == creationTime).OrderBy(c => c.StartTime).ToList();

                    var preStep = rollBackData.Records.Where(c => c.Id == parallelList.First().PreStepId).First();

                    // parallelList 中找所有需要恢复为等待的，移除他发起的后续任务操作，改为等待
                    //          所有并行的，找到最后办理者(把稿件送回至任务转发人的)， 移除他发起的后续任务操作，改为办结

                    Stack<Guid?> stack;
                    WorkFlowProcessDto exitTask = null;

                    foreach (var item in parallelList)
                    {
                        if (item.WaitingList.IsNullOrEmpty())  /*可能是多人并行 也可能是顺序执行中排在第一个的*/
                        {
                            //找并行路线里其他分支 可能存在的最后办理者
                            if (exitTask == null)
                            {
                                stack = new Stack<Guid?>();
                                stack.Push(preStep.TrunkId);

                                exitTask = FindExit(item, rollBackData.Records, stack);
                            }
                        }
                        else 
                        {
                            CheackWaitingData(rollBackData, item);  //parallelList 已经用StartTime排过序了，item.waiting中的任务一定先被检查，然后才轮到item
                        }
                    }

                    // 留在最后记录IdListToFinished，因为它可能改为办理完毕，也可能要改为等待，或删除
                    if (exitTask != null
                        && !rollBackData.IdListToRemve.Contains(exitTask.Id)
                        && !rollBackData.IdListToChangeToWaiting.Contains(exitTask.Id)
                        && !rollBackData.IdListToDo.Contains(exitTask.Id))
                    {
                        //移除exitTask的后代
                        rollBackData.IdListToRemve.AddRange(GetAllDescendant(exitTask.Id, rollBackData.Records, false));
                        rollBackData.IdListToFinished.Add(exitTask.Id);
                    }
                }
            }
            else
            {
                //主线上因为传阅需要支持跨步骤办理，所以独立出来分析（传阅任务跨步骤作为最后一人发起新步骤任务时，稿件回退可能不再适用递归）
                /*
                   假设步骤3 有三个并行的任务A、B、C, A是传阅任务可延后到下一步完成，则B办理送到步骤4，新增了任务D, D办理完毕后，A作为最后一人，
                     办理后送到步骤5。稿件要退到C处时，有A和B两个出口（需改为完成），如退到D处，则之前的递归方法找不到A这个出口
                */

                //所有stepCode大于task.StepCode的，都要移除(task是传阅的特殊讨论)，并找到这些里最小的那个stepCode的发起者，改为完成
                //同步骤里遍历主线，查找可能需要改为Wating的任务
                if(workFlowRollBackDiyService != null)
                {
                    workFlowRollBackDiyService.CheckBackToStep(rollBackData, task);
                }

                if (rollBackData.BackToStepCode <= 0)
                {
                    rollBackData.BackToStepCode = task.StepCode;
                    rollBackData.BackToNodeId = task.NodeId;
                }

                int stepCode = rollBackData.BackToStepCode;

                var taskDatas = rollBackData.Records
                    .Where(c => c.StepCode >= task.StepCode && c.TrunkId == null).OrderBy(c => c.StartTime);

                var exitTaskIds = new List<Guid>();
                //查找IdListToFinished
                foreach (var item in taskDatas)
                {
                    if(item.StepCode > stepCode)
                    {
                        var senderTask = rollBackData.Records.FirstOrDefault(c => c.Id == item.PreStepId);
                        if (senderTask != null && senderTask.StepCode == stepCode)
                        {
                            //找到出口（步骤的最后一个办理人）
                            exitTaskIds.Add(senderTask.Id);
                        }
                    }
                }

                //查找IdListToChangeToWaiting
                var waitingTaskData = taskDatas.Where(c => c.StepCode == stepCode && !c.WaitingList.IsNullOrEmpty())
                    .OrderBy(c=>c.StartTime);
                foreach (var item in waitingTaskData)
                {
                    CheackWaitingData(rollBackData, item);
                }

                foreach (var exitTaskId in exitTaskIds)
                {
                    if (!rollBackData.IdListToDo.Contains(exitTaskId)
                       && !rollBackData.IdListToChangeToWaiting.Contains(exitTaskId)
                       && !rollBackData.IdListToRemve.Contains(exitTaskId)
                       && !rollBackData.IdListToFinished.Contains(exitTaskId))
                    {
                        rollBackData.IdListToRemve.AddRange(GetAllDescendant(exitTaskId, rollBackData.Records, false));
                        rollBackData.IdListToFinished.Add(exitTaskId);
                    }
                }
            }
        }

        private void CheackWaitingData(WorkFlowRollBackData rollBackData, WorkFlowProcessDto item)
        {
            if (item.State != ActionState.Waiting)  // wait, todo, relate, Archive
            {
                var waiting = item.WaitingList.GetArryFromStrBySplit<Guid>(WorkFlowConst.SplitChars);

                if (rollBackData.IdListToDo.FirstOrDefault(c => waiting.Contains(c)) != Guid.Empty
                    || rollBackData.IdListToChangeToWaiting.FirstOrDefault(c => waiting.Contains(c)) != Guid.Empty)
                {
                    rollBackData.IdListToRemve.AddRange(GetAllDescendant(item.Id, rollBackData.Records, true));
                    rollBackData.IdListToChangeToWaiting.Add(item.Id);
                }
            }
        }

        private WorkFlowProcessDto FindExit(WorkFlowProcessDto item, List<WorkFlowProcessDto> records, Stack<Guid?> stack)
        {
            var nextOp = records.Where(c => c.PreStepId == item.Id).ToList();
            if (nextOp.Count > 0)
            {
                /*
                * topItem 是 item 的任务转发人，item的后代可能是新发起的支线，也可能是回送给任务转发人，
                *   还可能是自定义添加的新任务（主线,主线不再用这个方法查找）
                * TODO: 待优化， ☆ 也可能存在一些非常规的自定义操作，如越级送回到主线（可能是转发人的转发人）
                *           也可以考虑自动添加这些缺失的回送，但做特殊标记，不在UI端显示
                */
                var topItem = stack.Peek();
                if (nextOp.Any(c => c.TrunkId == topItem)/*并行操作结束*/)
                {
                    stack.Pop();
                    if (stack.Count == 0)
                    {
                        return item;
                    }

                    var exitTask = FindExit(nextOp.First()/*回归操作只有一个任务接收人*/, records, stack);
                    if (exitTask != null)
                    {
                        return exitTask;
                    }
                    stack.Push(topItem);
                }
                else
                {
                    //并行操作中的某人又发起了新的支线
                    stack.Push(item.TrunkId);
                    foreach (var item2 in nextOp)
                    {
                        var exitTask = FindExit(item2, records, stack);
                        if (exitTask != null)
                        {
                            return exitTask;
                        }
                    }
                    stack.Pop();
                }
            }
            return null;
        }

        private List<Guid> GetAllDescendant(Guid rootId, List<WorkFlowProcessDto> records, bool removeParallel)
        {
            var list = new List<Guid>();

            GetAllDescendant(rootId, records, list, removeParallel);

            return list;

        }
        private void GetAllDescendant(Guid parentId, List<WorkFlowProcessDto> records, List<Guid> result, bool removeParallel)
        {
            var subList = records.Where(c => c.PreStepId == parentId).ToList();
            foreach (var item in subList)
            {
                if (removeParallel)
                {
                    result.Add(item.Id);
                    GetAllDescendant(item.Id, records, result, true);
                }
                else if (!item.Parallel)
                {
                    result.Add(item.Id);
                    GetAllDescendant(item.Id, records, result, true);
                }
            }
        }

        private async Task ChangeDbDataForGoBackActionAsync(
            Guid taskId, WorkFlowRollBackData rollBackData, WorkFlowPaper paper, IWorkFlowRollBackDiyService workFlowRollBackDiyService, bool cleanMsg)
        {
            //throw new NotImplementedException();
            //Loger.Debug($"idListToRemve:{idListToRemve.ToJsonString()}");
            //Loger.Debug($"idListToChangeToWaiting:{idListToChangeToWaiting.ToJsonString()}");
            //Loger.Debug($"idListToChangeToToDo:{idListToChangeToToDo.ToJsonString()}");
            //Loger.Debug($"idListToFinished:{idListToFinished.ToJsonString()}");
            var paperId = paper.Id;

            var toToList = await WorkFlowProcessRepository.GetAllListAsync(c => rollBackData.IdListToDo.Contains( c.Id));
            var toToTask = toToList.FirstOrDefault(c => c.Id == taskId);
            if (toToList.Count > 0 && toToTask != null)
            {
                if (rollBackData.IdListToRemve != null && rollBackData.IdListToRemve.Count > 0)
                {
                    //1、删除日志等关联数据
                    await WorkFlowLogsRepository.BatchDeleteAsync(c => c.PaperId == paperId && c.ProcessId != null && rollBackData.IdListToRemve.Contains(c.ProcessId.Value));

                    await _workFlowRelationshipRepository.BatchDeleteAsync(
                            c => c.PaperId == paperId && (rollBackData.IdListToRemve.Contains(c.TaskId) || rollBackData.IdListToRemve.Contains(c.ResponsibilityId)));

                    await _workFlowProcessMsgRepository.BatchDeleteAsync(c => c.PaperId == paperId && rollBackData.IdListToRemve.Contains(c.TaskId));

                    //2、删除处理记录
                    await WorkFlowProcessRepository.BatchDeleteAsync(c => rollBackData.IdListToRemve.Contains(c.Id));
                }


                if (rollBackData.IdListToChangeToWaiting != null && rollBackData.IdListToChangeToWaiting.Count > 0)
                {
                    //1、删除日志等关联数据
                    await WorkFlowLogsRepository.BatchDeleteAsync(c => c.PaperId == paperId && c.ProcessId != null && rollBackData.IdListToChangeToWaiting.Contains(c.ProcessId.Value));

                    await _workFlowRelationshipRepository.BatchDeleteAsync(
                           c => c.PaperId == paperId && (rollBackData.IdListToChangeToWaiting.Contains(c.TaskId) || rollBackData.IdListToChangeToWaiting.Contains(c.ResponsibilityId)));

                    await _workFlowProcessMsgRepository.BatchDeleteAsync(c => c.PaperId == paperId && rollBackData.IdListToRemve.Contains(c.TaskId));

                    //2、修改处理记录（改为等待）
                    var toWaitList = await WorkFlowProcessRepository.GetAllListAsync(c => rollBackData.IdListToChangeToWaiting.Contains(c.Id));
                    foreach (var taskData in toWaitList)
                    {
                        taskData.MarkedTime = null;
                        taskData.HasMarked = false;
                        taskData.State = ActionState.Waiting;
                        taskData.FinishedTime = null;
                        taskData.PreOperatorId = taskData.PreStepId; // 这个字段在数据新建时和PreStepId一样，见WorkFlowManager
                        //if (taskData.IsDefaultMsg)
                        //{
                            taskData.Reply = null;
                            taskData.ReplyTime = null;
                        //}
                    }
                }

                if (rollBackData.IdListToFinished != null && rollBackData.IdListToFinished.Count > 0)
                {
                    //改日志
                    foreach (var itemId in rollBackData.IdListToFinished)
                    {
                        var item = rollBackData.Records.FirstOrDefault(c => c.Id == itemId);
                        if(item != null)
                        {
                            if (item.OperationType == OperationType.Processing)
                            {
                                await WorkFlowLogsRepository.BatchUpdateAsync(
                                    c => new WorkFlowLogs { Message = "办理完毕", NextOperator = "" },
                                    c => c.PaperId == paperId && c.ProcessId == itemId && c.Parallel == false
                                    );
                            }
                            else
                            {
                                await WorkFlowLogsRepository.BatchUpdateAsync(
                                    c => new WorkFlowLogs { Message = "传阅完毕", NextOperator = "" },
                                    c => c.PaperId == paperId && c.ProcessId == itemId && c.Parallel == false
                                    );
                            }
                        }
                    }
                }

                //3、修改稿件
                if (rollBackData.BackToNodeId != Guid.Empty)
                {
                    paper.ChangeNode(rollBackData.BackToNodeId);
                }

                //4、待办任务
                foreach (var taskData in toToList)
                {
                    taskData.MarkedTime = null;
                    taskData.HasMarked = false;
                    taskData.State = ActionState.Todo;
                    taskData.FinishedTime = null;
                    taskData.FinishedByTheWay = null;
                    taskData.HasRead = true;
                    taskData.IsHiddenInTable = false;
                    if (taskData.IsDefaultMsg || cleanMsg)
                    {
                        taskData.Reply = null;
                        taskData.ReplyTime = null;
                    }
                }
                // 移除ToDo对应的日志等
                await WorkFlowLogsRepository.BatchDeleteAsync(c => c.PaperId == paperId && c.Parallel == false && c.ProcessId != null && rollBackData.IdListToDo.Contains(c.ProcessId.Value));
                
                await _workFlowRelationshipRepository.BatchDeleteAsync(c => c.PaperId == paperId && rollBackData.IdListToDo.Contains(c.ResponsibilityId));

                // 恢复被同步取消的多对一关联
                foreach (var item in rollBackData.RelationshipsWithCanceled.Where(c => c.IsCanceled && c.StateModifierTaskId != null))
                {
                    //确认该数据不在要删除的清单中
                    if (!rollBackData.IdListToRemve.Contains(item.TaskId)
                        && !rollBackData.IdListToRemve.Contains(item.ResponsibilityId)
                        && !rollBackData.IdListToChangeToWaiting.Contains(item.TaskId)
                        && !rollBackData.IdListToChangeToWaiting.Contains(item.ResponsibilityId)
                        && !rollBackData.IdListToDo.Contains(item.ResponsibilityId)
                        )
                    {
                        if (rollBackData.IdListToDo.Contains(item.StateModifierTaskId.Value)
                            || rollBackData.IdListToRemve.Contains(item.StateModifierTaskId.Value)
                            || rollBackData.IdListToChangeToWaiting.Contains(item.StateModifierTaskId.Value))
                        {
                            var entity = await _workFlowRelationshipRepository.FirstOrDefaultAsync(c => c.Id == item.Id);
                            if (entity != null)
                            {
                                entity.IsCanceled = false;
                                entity.StateModifierTaskId = null;
                                entity.HasMarked = false;
                            }
                        }
                    }
                }

                if (workFlowRollBackDiyService != null)
                {
                    await workFlowRollBackDiyService.ChangeDbDataForGoBackActionAsync(taskId, rollBackData, paper, this);
                }

                // 判断是否退到了拟稿步骤
                var remainder = new List<Guid>();
                foreach (var item in rollBackData.Records)
                {
                    if (!rollBackData.IdListToRemve.Contains(item.Id))
                    {
                        remainder.Add(item.Id);
                    }
                }
                if(remainder.Count == 1)
                {
                    paper.ChangePaperState(PaperState.Draft);
                }
            }
        }
       
        #endregion
    }
}
